home *** CD-ROM | disk | FTP | other *** search
/ The X-Philes (2nd Revision) / The X-Philes Number 1 (1995).iso / xphiles / hp48_2 / star-1_0.tar / expr.c < prev    next >
C/C++ Source or Header  |  1991-03-22  |  12KB  |  657 lines

  1. /* expr.c -- STAR Expression Evaluator
  2.  
  3. This file is part of STAR, the Saturn Macro Assembler.
  4.  
  5.    STAR is not distributed by the Free Software Foundation. Do not ask
  6. them for a copy or how to obtain new releases. Instead, send e-mail to
  7. the address below. STAR is merely covered by the GNU General Public
  8. License.
  9.  
  10. Please send your comments, ideas, and bug reports to
  11. Jan Brittenson <bson@ai.mit.edu>
  12.  
  13. */
  14.  
  15.  
  16. /* Copyright (C) 1990, 1991 Jan Brittenson.
  17.  
  18.    STAR is free software; you can redistribute it and/or modify it
  19. under the terms of the GNU General Public License as published by the
  20. Free Software Foundation; either version 1, or (at your option) any
  21. later version.
  22.  
  23.    STAR is distributed in the hope that it will be useful, but WITHOUT
  24. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  25. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  26. for more details.
  27.  
  28.    You should have received a copy of the GNU General Public License
  29. along with STAR; see the file COPYING. If not, to obtain a copy, write
  30. to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
  31. USA, or send e-mail to bson@ai.mit.edu. */
  32.  
  33.  
  34. #include <stdio.h>
  35. #include <math.h>
  36. #include "sects.h"
  37. #include "star.h"
  38. #include "symbols.h"
  39. #include "ctt.h"
  40.  
  41.  
  42. /* External functions/data */
  43. extern SYM_ROOT
  44.   *symtbl;
  45.  
  46. extern
  47.   mtstr(), errcnt, pass;
  48.  
  49.  
  50. /* Global functions/data */
  51. CTT_ROOT
  52.   *reg_table,            /* Register transition tree */
  53.   *opx_table,            /* OPX transition tree */
  54.   *xopy_table;            /* XOPY transition tree */
  55.  
  56. struct val
  57.   (*defrdx)();            /* Default radix parser */
  58.  
  59. struct fstruct
  60.   *fhit;            /* Last operator called */
  61.  
  62. /* A few constants */
  63. struct val
  64.   val_zero,            /* INT 0 */
  65.   val_one,            /* INT 1 */
  66.   val_real0,            /* REAL 0 */
  67.   val_real1,            /* REAL 1 */
  68.   val_nullstr;            /* STRING `' */
  69.  
  70.  
  71. /* Local data (externally accessible) */
  72. char
  73.   expr_strings[32768],        /* 32kB of expression data space */
  74.   *expr_allp;            /* Allocation pointer */
  75.  
  76.  
  77. /* Initialize constants, etc */
  78. void expr_init()
  79. {
  80.   expr_allp = expr_strings;
  81.  
  82.   val_zero.type = VT_INT;
  83.   val_zero.vint = 0;
  84.  
  85.   val_one.type  = VT_INT;
  86.   val_one.vint  = 1;
  87.  
  88.   val_nullstr.type = VT_STR;
  89.   val_nullstr.vstr = "";
  90.  
  91.   val_real0.type = val_real1.type = VT_REAL;
  92.   val_real0.vdouble = 0.0;
  93.   val_real1.vdouble = 1.0;
  94. }
  95.  
  96.  
  97. /* Wrap integer into value */
  98. #ifndef __GNUC__
  99. struct val intval(i)
  100.   INT i;
  101. {
  102.   struct val tmp;
  103.  
  104.   tmp.type = VT_INT;
  105.   tmp.vint = i;
  106.  
  107.   return(tmp);
  108. }
  109. #endif
  110.  
  111.  
  112. /* True if data is in expression space */
  113. isexpr_data(p)
  114.   char *p;
  115. {
  116.   return(p >= expr_strings &&
  117.      p <= expr_strings + sizeof expr_strings);
  118. }
  119.  
  120.  
  121. /* Allocate data in expression space */
  122. char *expr_alloc(nbytes)
  123.   int nbytes;
  124. {
  125.   register char *tmp = expr_allp;
  126.  
  127.   if(nbytes & 15)
  128.     nbytes = (nbytes & ~15) + 16;
  129.  
  130.   if((expr_allp += nbytes) >= expr_strings + sizeof expr_strings)
  131.     fatal("Can't allocate %d bytes: expression data space exhausted",
  132.       nbytes);
  133.  
  134.   return(tmp);
  135. }
  136.  
  137.  
  138. /* Duplicate string in space reclaimable by expr_gc  */
  139. char *expr_strdup(str)
  140.   char *str;
  141. {
  142.   register char *tmp;
  143.   int n = strlen(str)+1;
  144.  
  145.   tmp = expr_alloc(n);
  146.  
  147.   bcopy(str, tmp, n+1);
  148.   return(tmp);
  149. }
  150.  
  151.  
  152. /* Duplicate macro in space reclaimable by expr_gc */
  153. struct macro *expr_dupmacro(mp)
  154.   struct macro *mp;
  155. {
  156.   int msize = sizeof *mp + (mp->nlines - 1) * sizeof(char *);
  157.   char **l;
  158.   struct marg *ma;
  159.   struct macro *m;
  160.  
  161.   /* Start out with current block data */
  162.   m = (struct macro *) expr_alloc(msize);
  163.   bcopy(mp, m, msize);
  164.  
  165.   /* Duplicate lines */
  166.   for(l = m->lines; l < m->lines + m->nlines; l++)
  167.     *l = expr_strdup(*l);
  168.  
  169.   /* Duplicate argument default values, if any*/
  170.   for(ma = m->args; ma < m->args + m->nargs; ma++)
  171.     ma->def  = (ma->def ? expr_strdup(ma->def) : NULL);
  172.  
  173.   return(m);
  174. }
  175.  
  176.  
  177. /* Duplicate macro */
  178. struct macro *dupmacro(mp)
  179.   struct macro *mp;
  180. {
  181.   int msize = sizeof *mp + (mp->nlines - 1) * sizeof(char *);
  182.   char **l;
  183.   struct marg *ma;
  184.   struct macro *m;
  185.   extern char *malloc(), *strdup();
  186.  
  187.   /* Start out with current block data */
  188.   if(!(m = (struct macro *) malloc(msize)))
  189.     fatal("Can't allocate %d bytes for macro definition", msize);
  190.       
  191.   bcopy(mp, m, msize);
  192.  
  193.   /* Duplicate lines */
  194.   for(l = m->lines; l < m->lines + m->nlines; l++)
  195.     *l = strdup(*l);
  196.  
  197.   /* Duplicate argument defaults */
  198.   for(ma = m->args; ma < m->args + m->nargs; ma++)
  199.     {
  200.       ma->def  = (ma->def ? strdup(ma->def) : NULL);
  201.     }
  202.  
  203.   return(m);
  204. }
  205.  
  206.  
  207. /* Reclaim expr alloc space */
  208. void expr_gc()
  209. {
  210.   expr_allp = expr_strings;
  211. }
  212.  
  213.  
  214. /* Make recoverable copy of value */
  215. struct val localize(v)
  216.   struct val v;
  217. {
  218.   switch(v.type)
  219.     {
  220.     case VT_INT:
  221.     case VT_REAL: return(v);
  222.     case VT_STR:
  223.  
  224.       v.vstr = expr_strdup(v.vstr);
  225.       return(v);
  226.  
  227.     case VT_MAC:
  228.  
  229.       v.vmacro = expr_dupmacro(v.vmacro);
  230.  
  231.       return(v);
  232.  
  233.     case VT_SECT:
  234.  
  235.     default:
  236.  
  237.       return(v);
  238.     }
  239. }
  240.  
  241.  
  242. /* Duplicate string */
  243. char *strdup(s)
  244.   char *s;
  245. {
  246.   register char *tmp;
  247.   extern char *malloc();
  248.  
  249.   if(!(tmp = malloc(strlen(s)+1)))
  250.     fatal("Can't allocate %d characters for string data", strlen(s)+1);
  251.  
  252.   strcpy(tmp, s);
  253.   return(tmp);
  254. }
  255.  
  256.  
  257. /* Make value independent of expr recoverable areas */
  258. struct val solidify(v)
  259.   struct val v;
  260. {
  261.   switch(v.type)
  262.     {
  263.     case VT_INT:
  264.     case VT_REAL: return(v);
  265.     case VT_STR:
  266.  
  267.       v.vstr = strdup(v.vstr);
  268.       return(v);
  269.  
  270.     case VT_MAC:
  271.  
  272.       v.vmacro = dupmacro(v.vmacro);
  273.       return(v);
  274.  
  275.     case VT_SECT:
  276.     default:
  277.       return(v);
  278.     }
  279. }
  280.  
  281.  
  282. /* Convert to string, output is localized */
  283. struct val tostr(v)
  284.   struct val v;
  285. {
  286.   char bf[64];
  287.  
  288.   switch(v.type)
  289.     {
  290.     case VT_STR: return(v);
  291.     case VT_REAL:
  292.  
  293. #ifdef __GNUC__
  294.       sprintf(bf, "%lg", (double) v.vdouble);
  295. #else
  296.       sprintf(bf, "%g", (double) v.vdouble);
  297. #endif
  298.       v.type = VT_STR;
  299.       v.vstr = expr_strdup(bf);
  300.       return(v);
  301.  
  302.     case VT_INT:
  303.  
  304.       sprintf(bf, "%ld", (INT) v.vint);
  305.       v.type = VT_STR;
  306.       v.vstr = expr_strdup(bf);
  307.       return(v);
  308.  
  309.     case VT_SECT:
  310.     case VT_MAC:
  311.     default:
  312.       v.type = VT_STR;
  313.       v.vstr = expr_strdup("");
  314.       return(v);
  315.     }
  316. }
  317.  
  318.  
  319. /* Wrap double as real */
  320. #ifndef __GNUC__
  321. struct val realval(d)
  322.   REAL d;
  323. {
  324.   struct val dval;
  325.  
  326.   dval.type = VT_REAL;
  327.   dval.vdouble = d;
  328.   return(dval);
  329. }
  330. #endif
  331.  
  332.  
  333. /* Convert to real */
  334. struct val toreal(v)
  335.   struct val v;
  336. {
  337.   switch(v.type)
  338.     {
  339.     case VT_REAL: return(v);
  340.     case VT_INT:
  341.  
  342.       v.type = VT_REAL;
  343.       v.vdouble = (REAL) v.vint;
  344.       return(v);
  345.  
  346.     case VT_STR:
  347.  
  348.       return(toreal(toint(v)));
  349.  
  350.     case VT_SECT:
  351.  
  352.       return(toreal(intval(v.vsect->sc_reloc)));
  353.  
  354.     case VT_MAC:
  355.     default:
  356.  
  357.       return(val_real0);
  358.     }
  359. }
  360.  
  361.  
  362. /* Convert to integer */
  363. struct val toint(v)
  364.   struct val v;
  365. {
  366.   register unsigned char *cp;
  367.   register l;
  368.   register INT acc;
  369.  
  370.   switch(v.type)
  371.     {
  372.     case VT_REAL:
  373.  
  374.       v.type = VT_INT;
  375.       v.vint = (INT) v.vdouble;
  376.  
  377.       /* Drop */
  378.  
  379.     case VT_INT: 
  380.  
  381.       return(v);
  382.  
  383.     case VT_STR:
  384.  
  385.       v.type = VT_INT;
  386.  
  387.       if((l = strlen(v.vstr)) > sizeof v.vint)
  388.     l = sizeof v.vint;
  389.  
  390.       for(acc = 0, cp = (unsigned char *) v.vstr+l;
  391.       cp > (unsigned char *) v.vstr; acc += *--cp)
  392.     acc <<= 8;
  393.       
  394.       v.vint = acc;
  395.       return(v);
  396.  
  397.     case VT_SECT:
  398.  
  399.       return(intval(v.vsect->sc_reloc));
  400.  
  401.     default:
  402.       return(val_zero);
  403.     }
  404. }
  405.  
  406.  
  407. /* Test if end of expression
  408.  * Arguments are terminated if end of string, ';', ',' or '>'
  409.  * Spaces are bypassed.
  410.  */
  411. #ifndef eoe
  412. static eoe(cp)
  413.   char *cp;
  414. {
  415.   /* Does it match the termination condition? */
  416.   return(!cp ||
  417.      *cp < '\040' || *cp == ';' || *cp == '(' || *cp == ',' ||
  418.      *cp == ':' || *cp == '[' || *cp == ')' || *cp == ']');
  419. }
  420. #endif
  421.  
  422.  
  423. /* Initialize parse transition tables */
  424. void init_op_tables()
  425. {
  426.   struct fstruct *opp;
  427.   SYM_NODE *opsym;
  428.   int isopx;
  429.   char opname[64];
  430.   struct val opval;
  431.   extern struct fstruct
  432.     funtbl[], regtbl[];
  433.  
  434.  
  435.   /* Initialize tables */
  436.   opx_table = ctt_new();
  437.   xopy_table = ctt_new();
  438.   reg_table = ctt_new();
  439.  
  440.   /* Loop tables and add */
  441.   for(opp = funtbl; opp->name; opp++)
  442.     {
  443.       isopx = opp->type & OPX;
  444.  
  445.       sprintf(opname, "%c%s", (isopx ? ';' : ','), opp->name);
  446.  
  447.       opval.type = VT_OP;
  448.       opval.vop = opp;
  449.  
  450.       opsym = sm_enter_sym(symtbl, opname, opval, F_HID);
  451.       ctt_add((isopx ? opx_table : xopy_table), opp->name, opsym);
  452.     }
  453.  
  454.   for(opp = regtbl; opp->name; opp++)
  455.     {
  456.       sprintf(opname, ":%s", opp->name);
  457.  
  458.       opval.type = VT_OP;
  459.       opval.vop = opp;
  460.  
  461.       opsym = sm_enter_sym(symtbl, opname, opval, F_HID);
  462.       ctt_add(reg_table, opp->name, opsym);
  463.     }
  464. }  
  465.  
  466.  
  467. /* Match OPX op */
  468. mtopx(cpp, funp)
  469.   char **cpp;
  470.   struct fstruct **funp;
  471. {
  472.   SYM_NODE *opsym;
  473.  
  474.   if(!cpp)
  475.     return(FALSE);
  476.  
  477. #ifdef NEVER
  478.   printf("mtopx(`%s'): called\n", *cpp); /* DEBUG */
  479. #endif
  480.  
  481.   if((opsym = ctt_find(opx_table, cpp)) && (opsym->value.type == VT_OP))
  482.     {
  483. #ifdef NEVER
  484.       printf("mtopx: OPX match, rest=`%s'\n", *cpp); /* DEBUG */
  485. #endif
  486.  
  487.       fhit = *funp = opsym->value.vop;
  488.       return(TRUE);
  489.     }
  490.  
  491. #ifdef NEVER
  492.   printf("mtopx: no match, rest=`%s'\n", *cpp);    /* DEBUG */
  493. #endif
  494.  
  495.   return(FALSE);
  496. }
  497.  
  498.  
  499. /* Match XOPY op */
  500. mtxopy(cpp, funp)
  501.   char **cpp;
  502.   struct fstruct **funp;
  503. {
  504.   SYM_NODE *opsym;
  505.  
  506.   if((opsym = ctt_find(xopy_table, cpp)) && (opsym->value.type == VT_OP))
  507.     {
  508.       fhit = *funp = opsym->value.vop;
  509.       return(TRUE);
  510.     }
  511.       
  512.   return(FALSE);
  513. }    
  514.  
  515.  
  516.  
  517. /* Evaluate a simple term.
  518.  * Parse symbol names and default radix numbers.
  519.  */
  520. evsimple(cpp, lp)
  521.   char **cpp;
  522.   struct val *lp;
  523. {
  524.   struct sstruct *symp;
  525.   char csav, *sp;
  526.   
  527.   sp = *cpp;
  528.   
  529.   /* Parse numeric if numerical
  530.    * Must be called before 'issym' because
  531.    * '0'-'9' are valid symbol characters.
  532.    */
  533.   if(**cpp >= '0' && **cpp <= '9')
  534.     {
  535.       /* Call default radix parser */
  536.       *lp = (*defrdx)(cpp);
  537.       return(TRUE);
  538.     }
  539.   
  540.   /* Is it a symol? */
  541.   if(!issym(*sp))
  542.     {
  543.       *lp = val_zero;
  544.       return(FALSE);
  545.     }
  546.   
  547.   /* Assume symbol. Set sp to point at first invalid character */
  548.   for(sp = *cpp; issym(*sp); sp++);
  549.   
  550.   /* Save old character and zero terminate */
  551.   csav = *sp;
  552.   *sp  = '\0';
  553.  
  554.   if(!(symp = sm_find_sym(symtbl, *cpp)) || (symp->flags & F_UDF))
  555.     {
  556.       *lp = localize(val_nullstr);
  557.       sgnerr("Undefined symbol `%s'", *cpp);
  558.     }
  559.   else
  560.     {
  561.       *lp  = localize(symp->value);
  562.       symp->flags |= F_REF;
  563.     }
  564.  
  565.   /* Skip past symbol and return copy of its value */
  566.   *cpp = sp;
  567.   *sp  = csav;
  568.   
  569.   *cpp = byspace(*cpp);
  570.  
  571.   return(TRUE);
  572. }
  573.  
  574.  
  575. /* Evaluate term */
  576. static struct val evterm(cpp)
  577.   char **cpp;
  578. {
  579.   struct fstruct *funp;
  580.   struct val tmpacc;
  581.   
  582.   *cpp = byspace(*cpp);
  583.  
  584.   /* Look if we have an OPX op */
  585.   if(mtopx(cpp, &funp))
  586.  
  587.     /* Fast evaluation? */
  588.     if(funp->type & F_FAST)
  589.  
  590.       /* Yes */
  591.       return((*funp->feval)(cpp));
  592.     else
  593.       /* No, recurse until there is no more left */
  594.       return((*funp->feval)(cpp, evterm(cpp)));
  595.   
  596.   /* No, go for simple term */
  597.   if(!evsimple(cpp, &tmpacc))
  598.     sgnerr("Bad expression syntax");
  599.   
  600.   /* Return value of term */
  601.   return(tmpacc);
  602. }
  603.  
  604.  
  605. /* Evaluate an 'op term' pair */
  606. static int evalop(cpp, accp)
  607.   char **cpp;
  608.   struct val *accp;
  609. {
  610.   struct fstruct *funp;
  611.   struct val termacc;
  612.   
  613.   /* Make sure we have an XOPY op */
  614.   if(!mtxopy(cpp, &funp))
  615.     {
  616.       sgnerr("Bad expression, operator expected");
  617.       return(FALSE);
  618.     }
  619.   
  620.   /* Now evaluate term */
  621.   termacc = evterm(cpp);
  622.   
  623.   /* Evaluate XOPY and update accumulator */
  624.   *accp = (*funp->feval)(cpp, *accp, termacc);
  625.   return(TRUE);
  626. }
  627.  
  628.  
  629. /* Evaluate an expression */
  630. struct val evexpr(cpp)
  631.   char **cpp;
  632. {
  633.   struct val acc;
  634.   
  635.   
  636.   /* Evaluate term */
  637.   acc = evterm(cpp);
  638.   
  639.   /* Test if end of expression */
  640.   if(eoe(*cpp))
  641.     return(acc);
  642.   
  643.   /* The following is: op term op term ... op term */
  644.   for(;;)
  645.     {
  646.       *cpp = byspace(*cpp);
  647.       
  648.       /* End of expression? */
  649.       if(eoe(*cpp))
  650.     return(acc);
  651.       
  652.       /* No - XOPY TERM follows */
  653.       if(!evalop(cpp, &acc))
  654.     return(acc);
  655.     }
  656. }
  657.